/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ceair.flight.refund.service.uatp.impl;

import com.ceair.flight.refund.dto.appmoblie.RefundApplyDto;
import com.ceair.flight.refund.dto.appmoblie.RefundTktDto;
import com.ceair.flight.refund.location.dao.IRefundApplyDao;
import com.ceair.flight.refund.location.dao.IRefundTktDao;
import com.ceair.flight.refund.location.dt.enums.RefundStatusEnum;
import com.ceair.flight.refund.service.external.ITicketOperation;
import com.ceair.flight.refund.service.external.TktRfFormRes;
import com.ceair.flight.refund.service.notification.IUatpRefundNotification;
import com.ceair.flight.refund.service.uatp.IGenRefNoService;
import com.ceair.flight.refund.service.uatp.ITktRefundNoGenerator;
import com.ceair.muservice.common.exception.MuServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;

/**
 *
 * @author youguilin
 */
@Service
//@Source(name = "004090")
public class GenRefNoServiceImpl implements IGenRefNoService {

    private static final Logger LOG = LoggerFactory.getLogger(GenRefNoServiceImpl.class);
    private static final String PAYMENT_CHANNEL_CODE_UATP = "UATP";
    //等待用户原支付卡信息,生成退票单
    public static final String WAITING_CARD_INFO_FOR_GENERATE_REFUND_NO = "WAITING_CARD_INFO;";
    //生成退票单号失败
    public static final String GENERATE_REFUND_NO_FAIL = "GENERATE_REFUND_NO_FAIL;";
    @Autowired
    private IRefundApplyDao applyDao;
    @Autowired
    private IRefundTktDao tktDao;
    @Autowired
    private ITicketOperation ticketOperation;
    @Autowired
    private ITktRefundNoGenerator refundNoGenerator;
    @Resource(name = "uatpRefundNotification")
    private IUatpRefundNotification uatpRefundNotification;


    /**
     * 生产退票单号并更新退票申请单信息
     *
     * @param apply
     * @return
     */
//    @Source(name = "004090001")
    @Override
    public boolean doGenRefNo(RefundApplyDto apply) {
        long applyId = apply.getId();
        RefundApplyDto refundApply = applyDao.getRefundApplyDto(applyId);
        if (refundApply == null) {
            throw new IllegalStateException("No refund apply record found with id " + applyId);
        }
        if (dealUatp(refundApply)) {
            return false;
        }
        //generate refund No
        TktRfFormRes tktRfFormRes = null;
        try {
            tktRfFormRes = refundNoGenerator.generateRefundNo(refundApply);
        } catch (Exception ex) {
            LOG.error("Generated refund no error for refund apply {}", applyId, ex);
            throw new MuServiceException("004090001001", "Generated refund no error for refund apply " + applyId);
        }
        return dealResponse(tktRfFormRes, refundApply);
    }

    @Override
    public boolean doGenRefNo(long refundApplyId) {
        RefundApplyDto refundApply = new RefundApplyDto();
        refundApply.setId(refundApplyId);
        return doGenRefNo(refundApply);
    }

    @Override
    public boolean doGenRefNo(long refundApplyId, String cardNo) {
        RefundApplyDto refundApply = applyDao.getRefundApplyDto(refundApplyId);
        if (refundApply == null) {
            throw new IllegalStateException("No refund apply record found with id " + refundApplyId);
        }
        return doGenRefNo(refundApply, cardNo);
    }

    private boolean doGenRefNo(RefundApplyDto refundApply, String cardNo) {
        long applyId = refundApply.getId();
        //generate refund No
        TktRfFormRes tktRfFormRes = null;
        try {
            tktRfFormRes = refundNoGenerator.generateRefundNo(refundApply, cardNo);
        } catch (Exception ex) {
            LOG.error("Generated refund no error for refund apply {}", applyId, ex);
            throw new MuServiceException("004090001001", "Generated refund no error for refund apply " + applyId);
        }
        return dealResponse(tktRfFormRes, refundApply);
    }

    private boolean dealUatp(RefundApplyDto refundApply) {
        long applyId = refundApply.getId();
        RefundTktDto refundTkt = refundApply.getRefundTkt();
        if (checkPayment(refundTkt)) {
            LOG.info("Found payment bank code is {}, need customer payment card to generate refund form NO", refundTkt.getPaymentChannelCode());
            boolean isSuccess = uatpRefundNotification.sendNotification(refundApply);
            LOG.info("Send UATP notification message {}", isSuccess ? "success" : "failed");
            if (RefundStatusEnum.WAITING_CARD_FOR_REFUND_NO != RefundStatusEnum.getByCode(refundApply.getStatus())) {
                //如果申请单已处在等待用户支付卡号时, 不再更新,
                String actionTip = WAITING_CARD_INFO_FOR_GENERATE_REFUND_NO;
                refundApply.setActionTip(actionTip);
                refundApply.setStatus(RefundStatusEnum.WAITING_CARD_FOR_REFUND_NO.getCode());
                LOG.info("Change refund apply '{}' status to {}", applyId, RefundStatusEnum.WAITING_CARD_FOR_REFUND_NO.name());
                refundApply.setUpdatDate(new Date());
                //Mybatis
                applyDao.updateRefundApply(refundApply);
            }
            return true;
        }
        return false;
    }

    private boolean dealResponse(TktRfFormRes tktRfFormRes, RefundApplyDto refundApply) {
        long applyId = refundApply.getId();
        RefundTktDto refundTkt = refundApply.getRefundTkt();
        if (tktRfFormRes != null && tktRfFormRes.isSuccess()) {
            String refundNo = tktRfFormRes.getRefundNo();
            refundTkt.setRefundTicketNo(refundNo);

            BigDecimal refundAmt = refundApply.getRefundAmount();
            Long refundPoints = refundApply.getRefundPoints();
            //退票金额及退票积分都为零, 退票单不进行退款, 退票但状态置为退票完成
            if ((refundAmt == null || refundAmt.compareTo(BigDecimal.ZERO) == 0)
                    && (refundPoints == null || refundPoints.intValue() == 0)) {
                LOG.info("Change refund apply '{}' status to {}", applyId, RefundStatusEnum.REFUNDED_DONE);
                refundApply.setStatus(RefundStatusEnum.REFUNDED_DONE.getCode());
            } else {
                LOG.info("Change refund apply '{}' status to {}", applyId, RefundStatusEnum.WAIT_MONEY_REFUND);
                refundApply.setStatus(RefundStatusEnum.WAIT_MONEY_REFUND.getCode());
            }

            refundApply.setActionTip("");
            refundApply.setUpdatDate(new Date());
            //Mybatis写法
            refundTkt.setRefundApply(refundApply);
            applyDao.updateRefundApply(refundApply);
            if (0!=refundTkt.getId()){
                tktDao.updateTktDtoById(refundTkt);
            }else{
                tktDao.saveRefundTktDto(refundTkt);
            }
            return true;
        } else if (RefundStatusEnum.SECOND_AUDIT_PASS == RefundStatusEnum.getByCode(refundApply.getStatus())) {
            //如果申请单已处在退票单号生成异常状态,
            String actionTip = GENERATE_REFUND_NO_FAIL;
            refundApply.setActionTip(actionTip);
            refundApply.setStatus(RefundStatusEnum.GENERATE_REFUND_NO_EXCEPTION.getCode());
            LOG.info("Change refund apply '{}' status to {}", applyId, RefundStatusEnum.GENERATE_REFUND_NO_EXCEPTION.name());
            refundApply.setUpdatDate(new Date());
        }
        //Mybatis写法
        applyDao.updateRefundApply(refundApply);
        return false;
    }

    /**
     * 检查支付方式的银行代号是否是UATP
     *
     * @return
     */
    private boolean checkPayment(RefundTktDto refundTkt) {
        String paymentChannelCode = refundTkt.getPaymentChannelCode();
        return paymentChannelCode != null && paymentChannelCode.contains(PAYMENT_CHANNEL_CODE_UATP);
    }

}
